home *** CD-ROM | disk | FTP | other *** search
/ Aminet 51 / Aminet 51 (2002)(GTI - Schatztruhe)[!][Oct 2002].iso / Aminet / util / arc / xadmasterdev.lha / xad / Sources / clients / Tar.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-08-20  |  8.9 KB  |  326 lines

  1. #ifndef XADMASTER_TAR_C
  2. #define XADMASTER_TAR_C
  3.  
  4. /* Programmheader
  5.  
  6.     Name:        Tar.c
  7.     Main:        xadmaster
  8.     Versionstring:    $VER: Tar.c 1.10 (12.08.2001)
  9.     Author:        SDI
  10.     Distribution:    Freeware
  11.     Description:    Tar file archiver client
  12.  
  13.  1.0   07.09.98 : first version
  14.  1.1   29.06.99 : now uses master free stuff
  15.  1.2   29.08.99 : now uses xfi_DataPos
  16.  1.3   15.09.99 : also strips / from TF_DIR entries
  17.  1.4   11.08.00 : cleaner design
  18.  1.5   20.11.00 : octtonum read one byte less than specified
  19.  1.6   17.12.00 : octtonum now accepts spaces at end also
  20.  1.7   25.03.01 : now uses xadAddFileEntry()
  21.  1.8   27.05.01 : added support for longname extension
  22.  1.9   01.07.01 : added support for second longname type
  23.  1.10  12.08.01 : added device and fifo support
  24. */
  25.  
  26. #include <proto/xadmaster.h>
  27. #include <dos/dos.h>
  28. #include <exec/memory.h>
  29. #include "SDI_compiler.h"
  30. #define SDI_TO_ANSI
  31. #include "SDI_ASM_STD_protos.h"
  32.  
  33. #ifndef XADMASTERFILE
  34. #define Tar_Client        FirstClient
  35. #define NEXTCLIENT        0
  36. #define XADMASTERVERSION    11
  37. UBYTE version[] = "$VER: Tar 1.10 (12.08.2001)";
  38. #endif
  39. #define TAR_VERSION        1
  40. #define TAR_REVISION        10
  41.  
  42. struct TarHeader
  43. {                /* byte offset */
  44.   UBYTE th_Name[100];        /*   0 */
  45.   UBYTE th_Mode[8];        /* 100 */
  46.   UBYTE th_UserID[8];        /* 108 */
  47.   UBYTE th_GroupID[8];        /* 116 */
  48.   UBYTE th_Size[12];        /* 124 */
  49.   UBYTE th_MTime[12];        /* 136 */
  50.   UBYTE th_Checksum[8];     /* 148 */
  51.   UBYTE th_Typeflag;        /* 156 */
  52.   UBYTE th_LinkName[100];    /* 157 */
  53.   UBYTE th_Magic[6];        /* 257 */
  54.   UBYTE th_Version[2];        /* 263 */
  55.   UBYTE th_UserName[32];    /* 265 */
  56.   UBYTE th_GroupName[32];    /* 297 */
  57.   UBYTE th_DevMajor[8];     /* 329 */
  58.   UBYTE th_DevMinor[8];     /* 337 */
  59.   UBYTE th_Prefix[155];     /* 345 */
  60.   UBYTE th_Pad[12];        /* 500 */
  61. };
  62.  
  63. /* Values used in Typeflag field.  */
  64. #define TF_FILE     '0'  /* Regular file */
  65. #define TF_AFILE    '\0' /* Regular file */
  66. #define TF_LINK     '1'  /* Link */
  67. #define TF_SYM        '2'  /* Reserved - but GNU tar uses this for links... */
  68. #define TF_CHAR     '3'  /* Character special */
  69. #define TF_BLOCK    '4'  /* Block special */
  70. #define TF_DIR        '5'  /* Drawer */
  71. #define TF_FIFO     '6'  /* FIFO special */
  72. #define TF_CONT     '7'  /* Reserved */
  73. #define TF_LONGLINK     'K'  /* longlinkname block, preceedes the full block */
  74. #define TF_LONGNAME     'L'  /* longname block, preceedes the full block */
  75.  
  76. static ULONG octtonum(STRPTR oct, LONG width, LONG *ok)
  77. {
  78.   ULONG i = 0;
  79.  
  80.   while(*oct == ' ' && width--)
  81.     ++oct;
  82.  
  83.   if(!*oct)
  84.     *ok = 0;
  85.   else
  86.   {
  87.     while(width-- && *oct >= '0' && *oct <= '7')
  88.      i = (i*8)+*(oct++)-'0';
  89.  
  90.     while(*oct == ' ' && width--)
  91.       ++oct;
  92.  
  93.     if(width > 0 && *oct)    /* an error, set error flag */
  94.       *ok = 0;
  95.   }
  96.  
  97.   return i;
  98. }
  99.  
  100. static BOOL checktarsum(struct TarHeader *th)
  101. {
  102.   LONG sc, i;
  103.   ULONG uc, checks;
  104.   
  105.   i = 1;
  106.   checks = octtonum(th->th_Checksum, 8, &i);
  107.   if(!i)
  108.     return 0;
  109.  
  110.   for(i = sc = uc = 0; i < 512; ++i)
  111.   {
  112.     sc += ((BYTE *) th)[i];
  113.     uc += ((UBYTE *) th)[i];
  114.   }
  115.   
  116.   for(i = 148; i < 156; ++i)
  117.   {
  118.     sc -= ((BYTE *) th)[i];
  119.     uc -= ((UBYTE *) th)[i];
  120.   }
  121.   sc += 8 * ' ';
  122.   uc += 8 * ' ';
  123.  
  124.   if(checks != uc && checks != (ULONG) sc)
  125.     return 0;
  126.   return 1;
  127. }
  128.  
  129. ASM(BOOL) Tar_RecogData(REG(d0, ULONG size), REG(a0, STRPTR data),
  130. REG(a6, struct xadMasterBase *xadMasterBase))
  131. {
  132.   if(data[0] > 0x1F && checktarsum((struct TarHeader *) data))
  133.     return 1;
  134.   else
  135.     return 0;
  136. }
  137.  
  138. ASM(LONG) Tar_GetInfo(REG(a0, struct xadArchiveInfo *ai),
  139. REG(a6, struct xadMasterBase *xadMasterBase))
  140. {
  141.   struct TarHeader th;
  142.   struct xadFileInfo *fi;
  143.   LONG err = 0, size, ok, a, b, d, i, pos;
  144.   STRPTR longname = 0, longlink = 0, name, link;
  145.  
  146.   while(!err && ai->xai_InPos < ai->xai_InSize && !(err = xadHookAccess(XADAC_READ, sizeof(struct TarHeader), &th, ai)))
  147.   {
  148.     if(!th.th_Name[0])
  149.       break;
  150.     ok = checktarsum(&th); /* check checksum and init ok */
  151.     size = octtonum(th.th_Size, 12, &ok);
  152.  
  153.     pos = ai->xai_InPos;
  154.     if(ok && th.th_Typeflag == TF_LONGNAME)
  155.     {
  156.       if((longname = xadAllocVec(size, MEMF_ANY)))
  157.       {
  158.         if(!(err = xadHookAccess(XADAC_READ, size, longname, ai)))
  159.         {
  160.           size %= 512;
  161.           if(size)
  162.             err = xadHookAccess(XADAC_INPUTSEEK, 512-size, 0, ai);
  163.         }
  164.       }
  165.       else
  166.         err = XADERR_NOMEMORY;
  167.     }
  168.     else if(ok && th.th_Typeflag == TF_LONGLINK)
  169.     {
  170.       if((longlink = xadAllocVec(size, MEMF_ANY)))
  171.       {
  172.         if(!(err = xadHookAccess(XADAC_READ, size, longlink, ai)))
  173.         {
  174.           size %= 512;
  175.           if(size)
  176.             err = xadHookAccess(XADAC_INPUTSEEK, 512-size, 0, ai);
  177.         }
  178.       }
  179.       else
  180.         err = XADERR_NOMEMORY;
  181.     }
  182.     else if(ok && (th.th_Typeflag == TF_FILE || th.th_Typeflag == TF_AFILE ||
  183.     th.th_Typeflag == TF_DIR || th.th_Typeflag == TF_SYM ||
  184.     th.th_Typeflag == TF_LINK || th.th_Typeflag == TF_BLOCK ||
  185.     th.th_Typeflag == TF_CHAR || th.th_Typeflag == TF_FIFO))
  186.     {
  187.       name = longname ? longname : th.th_Name;
  188.       link = longlink ? longlink : (th.th_LinkName[0] ? th.th_LinkName : 0);
  189.       a = strlen(name) + 1;
  190.  
  191.       if(name[a-2] == '/')
  192.       {
  193.     if(th.th_Typeflag == TF_AFILE || th.th_Typeflag == TF_FILE || th.th_Typeflag == TF_DIR)
  194.     {
  195.       name[--a-1] == 0;
  196.           th.th_Typeflag = TF_DIR;
  197.         }
  198.       }
  199.  
  200.       if(!longname && th.th_Prefix[0])
  201.         a += strlen(th.th_Prefix)+1;
  202.       
  203.       b = link ? 1 + strlen(link) : 0;
  204.       i = th.th_UserName[0] ? 1 + strlen(th.th_UserName) : 0;
  205.       d = th.th_GroupName[0] ? 1 + strlen(th.th_GroupName) : 0;
  206.  
  207.       if(!(fi = (struct xadFileInfo *) xadAllocObject(XADOBJ_FILEINFO,
  208.       XAD_OBJNAMESIZE, a+b+i+d, TAG_DONE)))
  209.         err = XADERR_NOMEMORY;
  210.       else
  211.       {
  212.         fi->xfi_DataPos = pos;
  213.         fi->xfi_Flags = XADFIF_SEEKDATAPOS;
  214.     if(th.th_Typeflag == TF_LINK || th.th_Typeflag == TF_SYM)
  215.       fi->xfi_Flags |= XADFIF_LINK;
  216.     else if(th.th_Typeflag == TF_DIR)
  217.     {
  218.       fi->xfi_Flags |= XADFIF_DIRECTORY;
  219.       size = 0;
  220.     }
  221.     else if(th.th_Typeflag == TF_FIFO)
  222.     {
  223.       fi->xfi_Flags |= XADFIF_EXTRACTONBUILD;
  224.       fi->xfi_FileType = XADFILETYPE_UNIXFIFO;
  225.     }
  226.     else if(th.th_Typeflag == TF_BLOCK || th.th_Typeflag == TF_CHAR)
  227.     {
  228.       fi->xfi_Flags |= XADFIF_EXTRACTONBUILD;
  229.       fi->xfi_FileType = th.th_Typeflag == TF_BLOCK ?
  230.       XADFILETYPE_UNIXBLOCKDEVICE : XADFILETYPE_UNIXCHARDEVICE;
  231.       /* do not care if this fails, as it is not that important */
  232.       if((fi->xfi_Special = xadAllocObjectA(XADOBJ_SPECIAL, 0)))
  233.       {
  234.         fi->xfi_Special->xfis_Type = XADSPECIALTYPE_UNIXDEVICE;
  235.         fi->xfi_Special->xfis_Data.xfis_UnixDevice.xfis_MajorVersion = octtonum(th.th_DevMajor, 8, &ok);
  236.         fi->xfi_Special->xfis_Data.xfis_UnixDevice.xfis_MinorVersion = octtonum(th.th_DevMinor, 8, &ok);
  237.       }
  238.     }
  239.     else
  240.     {
  241.       fi->xfi_Flags |= XADFIF_EXTRACTONBUILD;
  242.           fi->xfi_CrunchSize = fi->xfi_Size = size;
  243.         }
  244.  
  245.         if(!longname && th.th_Prefix[0])
  246.         {
  247.           STRPTR s, t;
  248.  
  249.           t = fi->xfi_FileName; s = th.th_Prefix;
  250.           while(*s)
  251.             *(t++) = *(s++);
  252.           if(*(t-1) != '/')
  253.             *(t++) = '/';
  254.           s = th.th_Name;
  255.           while(*s)
  256.             *(t++) = *(s++);
  257.           if(*(t-1) == '/')
  258.             --t;
  259.           *t = 0;
  260.         }
  261.         else
  262.           xadCopyMem(name, fi->xfi_FileName, a-1);
  263.         if(b)
  264.         {
  265.           fi->xfi_LinkName = fi->xfi_FileName + a;
  266.           xadCopyMem(link, fi->xfi_LinkName, b-1);
  267.         }
  268.         if(i)
  269.         {
  270.           fi->xfi_UserName = fi->xfi_FileName + a + b;
  271.           xadCopyMem(th.th_UserName, fi->xfi_UserName, i-1);
  272.         }
  273.         if(d)
  274.         {
  275.           fi->xfi_GroupName = fi->xfi_FileName + a + b + i;
  276.           xadCopyMem(th.th_GroupName, fi->xfi_GroupName, d-1);
  277.         }
  278.         fi->xfi_OwnerUID = octtonum(th.th_UserID, 8, &ok);
  279.         fi->xfi_OwnerGID = octtonum(th.th_GroupID, 8, &ok);
  280.  
  281.         xadConvertProtection(XAD_PROTUNIX, octtonum(th.th_Mode, 8, &ok),
  282.         XAD_GETPROTFILEINFO, fi, TAG_DONE);
  283.  
  284.         xadConvertDates(XAD_DATEUNIX, octtonum(th.th_MTime, 12, &ok),
  285.         XAD_MAKELOCALDATE, 1, XAD_GETDATEXADDATE, &fi->xfi_Date, TAG_DONE);
  286.  
  287.         if(th.th_Typeflag == TF_FILE || th.th_Typeflag == TF_AFILE)
  288.           size = (size+511)&~511;
  289.         else
  290.           size = 0;
  291.  
  292.         err = xadAddFileEntry(fi, ai, XAD_SETINPOS, ai->xai_InPos+size, TAG_DONE);
  293.       }
  294.       if(th.th_Typeflag != TF_LONGNAME && longname)
  295.       {
  296.         xadFreeObjectA(longname, 0); longname = 0;
  297.       }
  298.     }
  299.   }
  300.  
  301.   if(longname)
  302.     xadFreeObjectA(longname, 0);
  303.  
  304.   if(err)
  305.   {
  306.     ai->xai_Flags |= XADAIF_FILECORRUPT;
  307.     ai->xai_LastError = err;
  308.   }
  309.  
  310.   return (ai->xai_FileInfo ? 0 : err);
  311. }
  312.  
  313. ASM(LONG) Tar_UnArchive(REG(a0, struct xadArchiveInfo *ai),
  314. REG(a6, struct xadMasterBase *xadMasterBase))
  315. {
  316.   return xadHookAccess(XADAC_COPY, ai->xai_CurFile->xfi_Size, 0, ai);
  317. }
  318.  
  319. const struct xadClient Tar_Client = {
  320. NEXTCLIENT, XADCLIENT_VERSION, XADMASTERVERSION, TAR_VERSION, TAR_REVISION,
  321. 512, XADCF_FILEARCHIVER|XADCF_FREEFILEINFO|XADCF_FREESPECIALINFO, XADCID_TAR, "Tar",
  322. (BOOL (*)()) Tar_RecogData, (LONG (*)()) Tar_GetInfo,
  323. (LONG (*)()) Tar_UnArchive, 0};
  324.  
  325. #endif /* XADMASTER_TAR_C */
  326.